import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'styles.dart';
import 'view/PageViewEx.dart';
import 'view/RightSheet.dart';
import 'view/SearshPopupList.dart';


typedef SearchPopupListFilter = bool Function(String filter, int index);

class Common {

  static appUIStyle() {
    SystemChrome.setSystemUIOverlayStyle(Styles.uiStyle);
  }

  static TabBar buildTabBar(BuildContext context, PageTabs tabs, Color indicatorColor) {
    return TabBar(
        controller: tabs.controller,
        tabs: tabs.tabItems,

        indicatorColor: indicatorColor,
        onTap: (index) {
      tabs.onPageChanged?.call(index);
      tabs.pageController?.jumpTo(MediaQuery.of(context).size.width * index);
    });
  }

  static Widget buildAppBarTitle(Widget title, [String subtitle]) {
    return DefaultTextStyle(
      style: Styles.normalPrimaryContrastText,
      overflow: TextOverflow.ellipsis,
      maxLines: 1,
      child: (subtitle == null || subtitle.isEmpty) ? title:
      Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            title,
            subtitle == null || subtitle.isEmpty ? Container() : Text(subtitle, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(
              color: Styles.colorLight(Styles.primaryContrastValue, -0.05),
              fontSize: Styles.textMinSize,
            ))
          ]
      ),
    );
  }

  static AppBar buildAppBar(BuildContext context, {
    Widget title,
    Color indicatorColor,
    PageTabs tabs,
  }) {
    return AppBar(
        backgroundColor: Theme.of(context).primaryColor,
        title: title,
        centerTitle: true,
        elevation: Styles.elevation,
        bottom: tabs == null ? null : buildTabBar(context, tabs, indicatorColor)
    );
  }

  static Widget buildPageView(PageTabs tabs) {
    if (tabs.tabViews == null && tabs.tabViewDelegate == null)
      return null;
    return tabs.tabViewDelegate == null ? PageViewEx(
      controller: tabs.pageController,
      children: tabs.tabViews,
      onPageChanged: (index) {
        tabs.controller?.animateTo(index);
        tabs.onPageChanged?.call(index);
      },
    ) : PageViewEx.custom(
      childrenDelegate: tabs.tabViewDelegate,
      controller: tabs.pageController,
      onPageChanged: (index) {
        tabs.controller?.animateTo(index);
        tabs.onPageChanged?.call(index);
      },
    );
  }

  /// 顶部 tab bar
  static Widget buildTopScaffold(BuildContext context, {
    Widget title,
    bool resizeToAvoidBottomPadding = true,
    Widget floatingActionButton,
    FloatingActionButtonLocation floatingActionButtonLocation,
    List<Widget> persistentFooterButtons,
    AppBar appBar,
    Widget body,
    PageTabs tabs,
    Color indicatorColor,
    Widget bottomNavigationBar,
  }) {
    return Scaffold(
      resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
      floatingActionButton: SafeArea(child: floatingActionButton ?? Container()),
      floatingActionButtonLocation: floatingActionButtonLocation,
      persistentFooterButtons: persistentFooterButtons,
      appBar: appBar ?? buildAppBar(context, title: title, indicatorColor: indicatorColor, tabs: tabs),
      body: body != null ? body : (tabs == null) ? null : buildPageView(tabs),
      bottomNavigationBar: bottomNavigationBar,
    );
  }

  /// 底部 tab bar
  static Widget buildBottomScaffold(BuildContext context, {
    Widget title,
    bool resizeToAvoidBottomPadding = true,
    Widget floatingActionButton,
    FloatingActionButtonLocation floatingActionButtonLocation,
    List<Widget> persistentFooterButtons,
    AppBar appBar,
    Widget body,
    PageTabs tabs,
    Color indicatorColor,
    Widget bottomNavigationBar
  }) {
    return Scaffold(
      resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
      floatingActionButton: SafeArea(child: floatingActionButton ?? Container()),
      floatingActionButtonLocation: floatingActionButtonLocation,
      persistentFooterButtons: persistentFooterButtons,
      appBar: appBar ?? title == null ? null : AppBar(
          backgroundColor: Theme.of(context).primaryColor,
          title: title,
      ),
      body: body ?? (tabs == null) ? null : buildPageView(tabs),
      bottomNavigationBar: bottomNavigationBar ?? Material(
        color: Theme.of(context).primaryColor, //底部导航栏主题颜色
        child: SafeArea(
          child: tabs == null ? Container() : buildTabBar(context, tabs, indicatorColor),
        ),
      ),
    );
  }

  /// 显示菜单
  static showButtonMenu<T>(BuildContext context, State state, {
    double elevation = 8.0,
    @required List<PopupMenuEntry<T>> items,
    T initialValue,
    PopupMenuCanceled onCanceled,
    PopupMenuItemSelected<T> onSelected,
    double offsetX = 0.1,
    double offsetY = 0.0
  }) {
    final RenderBox button = context.findRenderObject();
    final RenderBox overlay = Overlay.of(context).context.findRenderObject();
    final RelativeRect position = new RelativeRect.fromRect(
      new Rect.fromPoints(
        button.localToGlobal(Offset(offsetX, offsetY), ancestor: overlay),
        button.localToGlobal(button.size.bottomRight(Offset.zero), ancestor: overlay),
      ),
      Offset.zero & overlay.size,
    );
    showMenu<T>(
      context: context,
      elevation: elevation,
      items: items,
      initialValue: initialValue,
      position: position,
    ).then<void>((T newValue) {
      if (!state.mounted)
        return null;
      if (newValue == null) {
        if (onCanceled != null)
          onCanceled();
        return null;
      }
      if (onSelected != null)
        onSelected(newValue);
    });
  }

  static List<PopupMenuEntry<T>> initFilterList<T>(String filter, List<PopupMenuEntry<T>> items, SearchPopupListFilter onFilter) {
    if (filter == null || filter.isEmpty || onFilter == null || items == null || items.isEmpty)
      return items;
    List<PopupMenuEntry<T>> v = [];
    filter = filter.toLowerCase();
    for (int i=0; i<items.length; i++) {
      if (onFilter(filter, i))
        v.add(items[i]);
    }
    return v;
  }

  /// 显示右滑菜单
  static showRightSheetMenu<T>(BuildContext context, State state, {
    double width,
    @required List<PopupMenuEntry<T>> items,
    T initialValue,
    String initialFilter,
    double itemExtent,
    PopupMenuCanceled onCanceled,
    PopupMenuItemSelected<T> onSelected,
    SearchPopupListFilter onFilter,
  }) async {
    List<PopupMenuEntry<T>> itemsFilter = initFilterList(initialFilter, items, onFilter);
    T result = await showModalRightSheet<T>(context: context, clickEmptyPop: false, builder: (context) {
      return Container(
        width: width ?? (MediaQuery.of(context).size.width - 50.0),
        child: SearchPopupList(
          initialFilter: initialFilter,
          onFilter: (key) {
            itemsFilter = initFilterList(key, items, onFilter);
          },
          itemCount: itemsFilter == null ? 0 : itemsFilter.length,
          itemBuilder: (context, index) {
            if (index < itemsFilter.length)
              return itemsFilter[index];
            return SizedBox(height: 0.0);
          },
          itemExtent: itemExtent,
        ),
      );
    });
    if (result == null) {
      if (onCanceled != null)
        onCanceled();
    } else {
      if (onSelected != null)
        onSelected(result);
    }
  }

  static Widget buildWaitView(String msg) {
    return Container(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          CircularProgressIndicator(strokeWidth: 1.0),
          Container(
            margin: const EdgeInsets.only(top: 16.0),
            child: msg == null || msg.isEmpty ? null : Text(msg, style: Styles.smallSubLightText),
          )
        ],
      ),
    );
  }

  /// 生成格子视图
  static List<Widget> buildGridView<T>(List<T> data, {int columns = 3, Widget builder(T v) , Widget builderRow(int row, List<Widget> items)}) {
    List<Widget> items = [];
    if (data == null || data.isEmpty)
      return items;
    List<Widget> rows;
    for (int i=0; i<data.length; i++) {
      if(i % columns == 0) {
        rows = new List<Widget>();
        Widget item = builderRow == null ? Row(
          children: rows,
        ) : builderRow(items.length, rows);
        if (item == null)
          item = new Row(children: rows);
        items.add(item);
      }
      rows.add(builder == null ? Expanded(child: Text("${data[i]}")) : builder(data[i]));
    }
    if (rows != null) {
      int lastRowCount = data.length % columns;
      if (lastRowCount > 0 && lastRowCount != columns) {
        for (int i = lastRowCount; i < columns; i++) {
          rows.add(Expanded(child: Container()));
        }
      }
    }
    return items;
  }

}

class PageTabs {
  final PageController pageController;
  final TabController controller;
  final List<Widget> tabItems;
  final List<Widget> tabViews;
  final SliverChildDelegate tabItemsDelegate;
  final SliverChildDelegate tabViewDelegate;
  final ValueChanged<int> onPageChanged;

  const PageTabs({this.controller, this.pageController, this.tabItems, this.tabViews, this.tabItemsDelegate, this.tabViewDelegate, this.onPageChanged}) : assert(
    pageController != null,
  );

}
